package panda.planner;

import java.io.StringReader;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;

import panda.parser.SQLLexer;
import panda.parser.cup.runtime.Symbol;
import panda.planner.util.ConditionFormalizer;
import panda.query.tree.QueryTreeNode;
import panda.syntax.CreateIndexStm;
import panda.syntax.CreateTableStm;
import panda.syntax.DeleteStm;
import panda.syntax.DropIndexStm;
import panda.syntax.DropTableStm;
import panda.syntax.SelectStm;
import panda.syntax.UpdateStm;
import panda.syntax.ValuesInsertStm;
import panda.transaction.Transaction;

public class Planner {
	QueryPlanner qp;
	UpdatePlanner up;
	
	public Planner(QueryPlanner qp, UpdatePlanner up) {
		this.qp = qp;
		this.up = up;
	}
	
	public QueryTreeNode executeSubQuery(SelectStm stm, Transaction tx) {
		return qp.createQueryTree(stm, tx);
	}
	
	public QueryTreeNode executeQuery(String stm, Transaction tx) {
		SQLLexer lx = new SQLLexer(new StringReader(stm));
		SelectStm ss;
		ArrayList al;
		try {
			Symbol sym = new panda.parser.parser(lx).parse();
			al = (ArrayList) sym.value;
		} catch (Exception e) {
			return null;
		}
		
		ss = (SelectStm)al.get(0);
		
		return executeQuery(ss, tx);
	}
	
	public QueryTreeNode executeQuery(SelectStm s, Transaction tx) {
		ConditionFormalizer.formalizeSelect(s, new HashMap(), new HashMap(), tx);
		return qp.createQueryTree(s, tx);
	}
	
	public static long parsertime = 0;
	
	public int executeUpdate(String stm, Transaction tx) {
		parsertime -= System.currentTimeMillis();
		SQLLexer lx = new SQLLexer(new StringReader(stm));
		Statement ss;
		ArrayList al;
		try {
			Symbol sym = new panda.parser.parser(lx).parse();
			al = (ArrayList)sym.value;
		} catch (Exception e) {
			return -1;
		}
		Object o = al.get(0);
		parsertime += System.currentTimeMillis();
		
		
		return executeUpdate((Object)o, tx);
	}
	
	public int executeUpdate(Object o, Transaction tx) {
		//Table manipulation
		if (o instanceof CreateTableStm) return up.executeCreateTable((CreateTableStm)o, tx);
		if (o instanceof DropTableStm) return up.executeDropTable((DropTableStm)o, tx);
		
		//Index manipulation
		if (o instanceof CreateIndexStm) return up.executeCreateIndex((CreateIndexStm)o, tx);
		if (o instanceof DropIndexStm) return up.executeDropIndex((DropIndexStm)o, tx);
		
		//Content manipulation
		if (o instanceof UpdateStm) {
			ConditionFormalizer.formalizeUpdate((UpdateStm)o, tx);
			return up.executeModify((UpdateStm)o, tx);
		}
		if (o instanceof DeleteStm) {
			ConditionFormalizer.formalizeDelete((DeleteStm)o, tx);
			return up.executeDelete((DeleteStm)o, tx);
		}
		if (o instanceof ValuesInsertStm) return up.executeInsertValues((ValuesInsertStm)o, tx);
		
		return -1;
		
	}
}
